import { v4 } from "uuid";
import { _fetch, createFetchFn, copy } from "./common";

/**
 * build a new request 
 * @param {*} fullRequestAndResponse 
 * @returns 
 */
export function buildRequest(fullRequestAndResponse) {
  const newFullRequest = {
    getContent: fullRequestAndResponse.getContent,
    ...fullRequestAndResponse,
    plainUrl: fullRequestAndResponse.request.url.split("?")?.[0],
    key: v4(),
  };
  const pathArr = newFullRequest.plainUrl.split("/");
  const name = pathArr[pathArr.length - 1];
  newFullRequest.name = name;
  return newFullRequest;
}

const requestMethod = {
  GET: (request) => {
    const ret = {};
    request.request.queryString.forEach((item) => {
      ret[item.name] = item.value;
    });
    return ret;
  },
  POST: (request) => {
    const jsonStr = request.request.postData.text;
    return jsonStr ? JSON.parse(jsonStr) : {};
  },
};

/**
 * parse params 
 * @param {*} request 
 * @returns 
 */
export function parseParams(request) {
  const method = request.request.method;
  return requestMethod[method] && requestMethod[method](request);
}

export function getDefaultRequestBody(request) {
  return {
    headers: {},
    referrer: "",
    referrerPolicy: "origin",
    body: null,
    method: "",
    mode: "cors",
    credentials: "",
    url: request.url,
  };
} 
function buildRequestParams(request) {
  const ret = getDefaultRequestBody(request);
  
  let requestHeaders = request.headers || [];
  if (Array.isArray(requestHeaders)) {
    requestHeaders.forEach((element) => {
      ret.headers[element.name] = element.value;
    });
  } else if (typeof requestHeaders === "object") {
    Object.keys(request.headers).forEach(key => {
      const realKey = requestHeaders[key]?.name;
      const realValue = requestHeaders[key]?.value;
      ret.headers[realKey] = realValue;
    });
  }
 
  if (request.url && request.url.includes("?")) {
    ret["referrer"] = request.url?.split("?")[0];
  } else {
    ret["referrer"] = request.url;
  }

  if (request.method === "POST") {
    ret["body"] = request.postData.text;
  }

  ret["method"] = request.method;

  if (request.url.includes("https")) {
    ret["credentials"] = "include";
  } else {
    delete ret["credentials"];
  }
  return ret;
}

export function parseRequestParams(fullRequest) {
  const { request } = fullRequest;
  return buildRequestParams(request);
}

function paramsToQuery(params) {
  if (!params) return "";
  return Object.keys(params).map(key => `${key}=${params[key]}`).join("&");
}

export function createAvailableRequest(fullRequest, params) {
  const requestParams = parseRequestParams(fullRequest);

  if (params) {
    switch (requestParams.method) {
    case "POST":
      requestParams.body = JSON.stringify(params);
      break;
    case "GET":
      requestParams.url = `${fullRequest.plainUrl}?${paramsToQuery(params)}`;
      break;
    }
  }

  return requestParams;
}

export function sendRequest(requestParams, successCallback, errorCallback) {
  _fetch(requestParams.url, requestParams)
    .then(() => {
      successCallback && successCallback(requestParams);
    })
    .catch((e) => {
      errorCallback && errorCallback(requestParams, e);
    });
}

export function repaly(fullRequest, params) {
  sendRequest(createAvailableRequest(fullRequest, params));
}

/**
 * copy as fetch
 * @param {*} fullRequest 
 * @param {*} params 
 */
export function copyAsFetch(fullRequest, params) {
  const requestParams = createAvailableRequest(fullRequest, params);
  const { url } = requestParams;
  const fetchStr = createFetchFn(url, requestParams);
  copy(fetchStr);
}

export function copyPayloadAsJson(fullRequest) {
  const payload = parseParams(fullRequest);
  copy(JSON.stringify(payload));
}